import {clear,skill} from  './function.js'
import {Socket} from "./ConnectSocket.js";

function game(){
    //1找对象
    clear();
    var ws = new Socket();   //设置全局变量 连接的重要性!
    var oUl=document.getElementById("ul1");
    var lead = '' ;
    var aLi=document.getElementsByTagName('li');
    var currentClick  = null; //用户点击方块

    var oBtn = document.getElementById("btn");
    //找到起始点，因为我们给起始点设置了不同的样式 所以可以通过样式可以找到起始点
    var beginLi= document.getElementsByClassName("lead");

    var endLi = '';
    //定义开始队列数组 open队列: 收集可能会需要走的路线 要走的路线放在open队列中
    var openArr=[];
    //定义结束队列数组 close队列: 排除掉不能走的路线  不走的路线放在close队列中
    var closeArr=[];
    //最终路线数组
    var resultParent=[];
    var currentPath = ''; //当前路径
    var jude = 0;
    var start =0;
    var stop = null
    var speed = 2;   //步数
    var size = 30;   //方格大小
    var truncation = 0;  //计用户是否中途扭头

    var font = 0; //判断中途是否截断

    //创建一个数组来表示地图,这个地图 20 * 20 其中值为1 表示起始点 值为2表示障碍物 值为3表示目标节点
    var map = [
        5,5,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,
        5,5,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,2,4,4,4,4,4,2,0,0,0,0,0,
        5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,2,4,0,0,0,4,2,0,0,0,0,0,
        0,0,2,0,0,0,0,0,5,5,0,0,0,0,0,0,0,2,0,0,0,0,4,4,0,0,0,0,2,4,4,4,4,4,2,0,0,0,0,0,
        0,0,0,0,0,2,0,2,5,5,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,
        0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,2,0,0,0,0,2,5,5,5,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,2,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,2,5,5,5,5,5,5,5,5,5,5,5,5,3,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
        0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,3,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,2,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    ];

    /*
     定义创建地图函数
     */

    /*
 定义初始函数
  */
    function init(){
        //在这个函数中需要动态创建li，通过调用封装好的函数实现
        createMap();
        //点击按钮的时候 需要去收集可能走的路线

        for(let i =0; i<aLi.length;i++){
            aLi[i].onclick = function (){
                if (this.className == 'style2'){
                    return;
                }
                currentClick = this

                if(truncation == 1) {     //步数正在执行中

                    clearRe();      //调用扭头函数

                }else if (truncation == 0){               //步数未在执行中

                    if(start !=0) {
                                   //判断是否第一次走 如果不是 则执行
                        Rest();

                    }
                    startZB(); //预处理
                }
            }
        }

    }
    //调用初始化函数
    init();

    var connect =setInterval(function(){   //重复判断是否连接成功

             if (ws.jude == 1){
                clearInterval(connect);
               for(var index in ws.idArr) {

                   var lead = document.createElement('div');
                  if (ws.idArr[index] == ws.userId) {
                      lead.style.left = 0 + 'px';
                  }else{
                      lead.style.left = 30 + 'px';
                  }
                   lead.style.top = 0 + 'px';

                   lead.className = 'lead'
                   lead.id = 'lead' + ws.idArr[index];
                   lead.innerHTML = '<img src="img/鬼.gif">'
                   oUl.appendChild(lead);

                   if (ws.idArr[index] == ws.userId) {
                        openArr.push(lead);
                       beginLi = [];
                       beginLi.push(lead);
                   }
               }
               var parent = document.getElementById('parent');
                 //装载技能函数
                 skill(document.getElementById('lead'+ws.userId),oUl,ws,parent);
                   currentClick = aLi[1];
                 if(start == 0) {

                     startZB(); //预处理

                 }
                 start ++;
             }
    },100);


    function createMap(){
        //定义li的大小
        var liSize=30;
        for(var i=0;i<map.length;i++){
            //创建元素
            var oLi=document.createElement("li");
            //设置宽高re
            oLi.style.width=liSize + "px";
            oLi.style.height=liSize + "px";
            oLi.index = i;
            //添加到ul中
            oUl.appendChild(oLi);
            //判断map元素的值来设置起始点
            if(map[i]==1){
                //如果map值为1 设置样式1 背景为红 表示起始点
                oLi.className="style1";
                //当元素刚开始创建的时候,open队列中的元素只有 起始节点 也就是说将红色点都放到open队列中 并且刚开始的时候起始点只有一个
              var left =  oLi.offsetLeft;
              var top =   oLi.offsetTop;

            }else if(map[i]==2){
                //如果map值为2 设置样式2 背景为黑 表示障碍物
                oLi.className="style2";
                //把黑色的点都放到close队列中 这些作为障碍物 是不会走的
                oLi.innerHTML = "<img src='img/障碍物.png'>"
                closeArr.push(oLi);
            }else if(map[i]==4){
                //如果map值为2 设置样式2 背景为黑 表示障碍物
                oLi.className="style2";
                //把黑色的点都放到close队列中 这些作为障碍物 是不会走的
                oLi.innerHTML = "<img src='img/水.png'>"
                closeArr.push(oLi);
            }else if(map[i] == 3){
                oLi.className ='bk'
                oLi.innerHTML = "<img src='img/木板.png'>"
            }else if(map[i] == 5){
                oLi.className ='bk'
                oLi.innerHTML = "<img src='img/石.png'>"
            }
            else{
                oLi.className ='bk'
            }
        }
        //ul的宽带等于 ul的左边 1 + 20个节点的宽带 20*(liSize+1)  其中 liSize+1 是因为 节点有1个像素的右边框
        oUl.style.width=40*(liSize)+"px";
    }

    /*
       估价函数封装,传入一个节点给给他一个估值
        */
    function fn(nowLi){
        return g(nowLi)+h(nowLi)
    }
    //初始点到当前节点的实际代价
    function g(nowLi){
        //勾股定理
        //横坐标的插值 beginLi[0] 开始节点 nowLi表示当前正在被估值的节点
        var a= nowLi.offsetLeft-beginLi[0].offsetLeft;
        var b= nowLi.offsetTop-beginLi[0].offsetTop;
        //勾股定理 开方得到两点之间最短距离
        return Math.sqrt(a*a+b*b);
    }
    //当前节点到目标点的实际代价
    function h(nowLi) {
        //勾股定理,这里和g函数一样的原理
        var a= nowLi.offsetLeft-endLi[0].offsetLeft;
        var b=nowLi.offsetTop - endLi[0].offsetTop;
        return Math.sqrt(a*a+b*b);
    }

    /*
     封装函数 实现开始队列中元素的添加
     */
    function openFn() {
        //nodeLi 表示 当前open队列中的元素 也就是说 先去除第一个起始节点
        //shift 方法作用: 把数组中的第一个元素删除,并且返回这个被删除的元素
         if(openArr.length == 0){
             openArr.push(currentPath);
             return ;
         }

        var nodeLi=openArr.shift();
        //如果nodeLi 和endLi 一样了 那么证明原件走到目标点了，这个时候需要停止调用
        if(nodeLi == endLi[0]){
            closeFn(endLi[0]);
            showPath();
            return;
        }
        //把openArr中删除的这个li节点,添加到closeArr中 这里调用closeFn函数实现
        closeFn(nodeLi);
        //接下来 需要找到 nodeLi周围的节点
        findLi(nodeLi);
        //经过上面的步骤 已经能够找到相邻的元素了 接下来需要对这些元素的估值进行排序
        openArr.sort(function (li1,li2) {
            return li1.num - li2.num
        });
        //进行递归操作 找下一步需要走的节点 在这个过程中,也需要执行相同的步
        //那就是查找相邻的节点 但是查找出来的结果可能和上次的重复,也就是说上一次动作已经把这个元素添加到open队列中了
        //那就没有必要在进行push 所以还需要在过滤函数中加一段代码
        openFn();
    }
    /*
    封装函数 实现结束队列中元素的添加
     */
    function closeFn(nodeLi) {
        //open队列中删除的元素 被push到close队列中
        closeArr.push(nodeLi);
    }
    /*
    封装函数查找某个节点周围的节点
     */
    function findLi(nodeLi){
        //创建一个结果数组 把查找的结果放到这个数组中
        var result=[];
        //循环所有的li节点
        for(var i=0;i<aLi.length;i++){
            //如果经过过滤 返回的是true 表示这个节点不是障碍物 那么需要添加到result结果组中
            if(filter(aLi[i])){
                result.push(aLi[i]);
            }
        }
        //接下来需要在没有障碍物的结果中去找 和 当前节点相邻的节点
        //判断条件是 他们的纵横坐标的差值小于 等于 网格大小
        for(var i=0;i<result.length;i++){
            if(Math.abs(nodeLi.offsetLeft - result[i].offsetLeft)<=30 && Math.abs(nodeLi.offsetTop - result[i].offsetTop)<=30){
            // if(Math.abs(nodeLi.offsetLeft - result[i].offsetLeft) == 0 && Math.abs(nodeLi.offsetTop - result[i].offsetTop)<=30 || Math.abs(nodeLi.offsetLeft - result[i].offsetLeft) <= 30 && Math.abs(nodeLi.offsetTop - result[i].offsetTop)==0){
                //这里result[i]就是当前目标点相邻的节点 把这些节点传入到估价函数就能得到他们的估值,并且要把这些估值挂载到他们自身的一个自定义属性上
                result[i].num = fn(result[i]);
                //nodeLi 是当前的位置 result[i]是当前位置的相邻的点 下一次要走的位置就在这几个点中,所以给result[i]定义一个parent属性
                //来存上一次的路径,最终把这些路径联系起来就是完整路径
                result[i].parent=nodeLi;
                //把已经经过估值的li添加到openArr中
                openArr.push(result[i]);
            }
        }
    }

    /**
     * 封装函数 实现过滤功能
     * 这个函数的功能就是 接收一个li 判断是否是障碍物 如果是 就返回false 如果不是就返回true
     */
    function filter(nodeLi) {
        //循环close队列中的所有元素 与传过来的节点进行比对 如果比对成功 返回false
        for(var i=0;i<closeArr.length;i++){
            if(nodeLi == closeArr[i]){
                return false;
            }
        }
        for (var i=0;i<openArr.length;i++){
            if(nodeLi == openArr[i]){
                return false;
            }
        }
        //如果循环玩都没有匹配上 那么证明当前传过来的 li节点 并不是障碍物
        return true;
    }

    /**
     * 定义一个函数来找到上一次走过的节点
     */
    function findParent(li) {
        let left = li.offsetLeft - li.parent.offsetLeft;
        let top = li.offsetTop - li.parent.offsetTop;
        let num = {top:top,left:left,list:li}
        resultParent.unshift(num);
        if(li.parent == beginLi[0]){
            return;
        }
        findParent(li.parent);
    }

    /*
      打印出所走过的路径
     */
    function showPath() {
        //closeArr中最后一个 就是 找到目标点的前一个位置 因为走过的位置都会被存到closeArr
        var lastLi = closeArr.pop();
        var iNow = 0;
        //调用findParent函数 来找上一个节点
        resultParent = [];
        findParent(lastLi);
        var m=jude;
        jude++;
        var storage = 0;
        var fps = 60
        var fpsInterval = 1000 / fps
        var last = new Date().getTime() //上次执行的时刻
        lead = document.getElementById('lead'+ws.userId);
        var leftNum = 0;
        var topNum = 0;
        var tack = function () {

            stop = window.requestAnimationFrame(tack)
             leftNum = 0;
             topNum = 0;
            if(truncation !=2 ) {    //判断用户是否已经下达扭头命令
                
                truncation = 1;
            }
            var now = new Date().getTime()
            var elapsed = now - last;
            // 经过了足够的时间
            if (elapsed > fpsInterval) {
                last = now - (elapsed % fpsInterval); //校正当前时间
                // 循环的代码
                // drawSomething()
                currentPath = resultParent[iNow].list;
                var current = resultParent[iNow]
                for (var item in resultParent){

                    if(resultParent[item] == endLi[0]){

                        continue;

                    }

                }
                var item = current.left == 0 ? true : false;

                var left = current.left;

                var top = current.top;

                storage += speed;


                if(left < 0){
                    leftNum = speed * -1
                }else if (left > 0){
                    leftNum = speed;
                }

                if(top < 0){
                    topNum = speed * -1
                }else if (top > 0){
                    topNum = speed;
                }

                 //应当接收到数据完后再走
                 if(ws.jude == 1){
                     let uPro = document.getElementById('lead'+ws.userId);
                     //获取当前对象的明确路径
                     let leftCount = uPro.offsetLeft;
                     let topCount = uPro.offsetTop;
                     var data = {
                          action:'hello',
                          class:'Index',
                          content:{
                             user:ws.userId,top:topNum,left:leftNum,leftCount,topCount
                                  }
                     };

                     data = JSON.stringify(data);

                     ws.ws.send(data);



                 }else {

                      console.log('还未连接成功');

                 }

                if(storage == size){
                    iNow++;
                    storage = 0;
                    if(truncation == 2) {
                        truncation = 0;
                        window.cancelAnimationFrame(stop);
                        Rest();
                        startZB();
                        return ;
                    }
                }

                if(iNow == resultParent.length){
                    window.cancelAnimationFrame(stop);
                    beginLi = [];
                    beginLi.push(endLi[0]);
                    resultParent = [];
                    endLi[0].className ='bk'
                    truncation = 0;
                }
            }
        }

        tack();

        ws.message(function(evt){

         // console.log(evt);
            var line = JSON.parse(evt.data);

            if(line.type == 'skill'){//收到创建子弹消息

                if(line.user == ws.userId){
                    return ;
                }

                var zidan = document.createElement('div');
                var lead = document.getElementById('lead'+ws.userId);

                zidan.className = 'skill '+line.name;
                zidan.style.position='absolute'
                zidan.style.height=30 + 'px';
                zidan.style.width=30 + 'px';
                zidan.style.left = lead.offsetLeft +'px';
                zidan.style.top = lead.offsetTop +'px';
                zidan.innerHTML = '<img src="img/0.png">'
                oUl.appendChild(zidan);

                return;
            }


            if(line.type == 'Cskill'){
                var skill = document.getElementsByClassName(line.name)[0];
                skill.style.left = line.left + 'px';
                skill.style.top = line.top + 'px';
                var lead = document.getElementsByClassName('lead');
                for (var i=0;i<lead.length;i++){
                    // console.log('触发了');
                    if(lead[i].id == 'lead'+line.user){
                        continue;
                    }
                    if(pz(skill,lead[i])){
                        console.log('碰到了');
                        //触发死亡信息
                        //获取死亡Id
                        let id = lead[i].id;
                        // ws.send()    //发送死亡讯息

                    }
                }
                return;
            }


            if(line.type =='uId') {

                if(line['uId'] == line['hId']){
                    return;
                }

                (function () {

                    var he = document.createElement('div');
                    he.style.left = line.leftCount + 'px';
                    he.style.top = line.topCount + 'px';
                    he.className = 'lead'
                    he.id = 'lead' + line['hId'];
                    he.innerHTML = '<img src="img/鬼.gif">'
                    oUl.appendChild(he);
                    console.log('走了'+he);

                })();

                return;
            }

            var we = document.getElementById('lead'+line['user']);
            var parent = document.getElementById('parent');
            leftNum = line.left;

            topNum = line.top
            if(line.user == ws.userId){
                 parent.scrollLeft = (we.offsetLeft - 150);
            }
            // console.log(line.leftCount);
            we.style.top = (line.topCount + line.top)  + 'px';

            we.style.left =  (line.leftCount + line.left) + 'px';

        })


    }

    function clearRe(){
         truncation = 2
    }

    function Rest(){
        openArr=[];
        openArr.push(currentPath);
        beginLi =[]
        beginLi.push(currentPath);
        AgainClose();
    }

    function AgainClose(){
        closeArr = [];
        for(var i=0;i<map.length;i++){
            if(map[i]==2){
                //如果map值为2 设置样式2 背景为黑 表示障碍物
                aLi[i].className="style2";
                //把黑色的点都放到close队列中 这些作为障碍物 是不会走的
                closeArr.push(aLi[i]);
            }else if(map[i]==4){
                //如果map值为2 设置样式2 背景为黑 表示障碍物
                aLi[i].className="style2";
                //把黑色的点都放到close队列中 这些作为障碍物 是不会走的
                closeArr.push(aLi[i]);
            }
        }
    }

    function startZB(){

        endLi=clear();
        currentClick.className="style3";
        openFn();

    }

    function pz(dom1,dom2){
          var dom1Top = dom1.offsetTop;
          var dom1Bottom = dom1Top + dom1.offsetHeight;
          var dom1Left = dom1.offsetLeft;
          var dom1Right = dom1Left + dom1.offsetWidth;

          var dom2Top = dom2.offsetTop;
          var dom2Bottom = dom2Top + dom2.offsetHeight;
          var dom2Left = dom2.offsetLeft;
          var dom2Right = dom2Left + dom2.offsetWidth;

          if(dom1Top > dom2Bottom || dom1Bottom < dom2Top || dom1Left > dom2Right || dom1Right < dom2Left )
          {
                return false;
          }else{
               return  true;
          }

    }


}




export {
    game as game
}